package com.qigao.mall.channel.alipay;

import com.alibaba.fastjson.JSONObject;
import com.qigao.mall.channel.ChannelCore;
import com.qigao.mall.channel.config.ChannelConstant;
import com.qigao.mall.commons.dto.MerChannelDto;
import com.qigao.mall.commons.enums.ChannelCodeEnum;
import com.qigao.mall.commons.param.ChannelReqParam;
import com.qigao.mall.commons.param.ChannelRespParam;
import com.qigao.mall.commons.utils.DateUtil;
import com.qigao.mall.commons.utils.HttpClientUtil;
import com.qigao.mall.commons.utils.PairString;
import com.qigao.mall.commons.utils.RSAUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author:luiz
 * @Date: 2018/5/28 11:16
 * @Descripton:
 * @Modify :
 **/
@Service
public abstract class AbstractAliPay implements ChannelCore {
    private static final Logger logger= LoggerFactory.getLogger(AbstractAliPay.class);
    @Resource
    ChannelConstant channelConstant;


    protected abstract String getTradeMethod();

    @Override
    public ChannelRespParam channelProcess(MerChannelDto merChannelDto, ChannelReqParam channelReqParam) {
        //1.构造请求参数
        Map reqContent=buildReqParam(merChannelDto,channelReqParam);
        logger.info("[支付宝交易]请求参数:{}",reqContent);
        //2.发送请求
        String reqUrl=channelConstant.getAlipayUrl();
        String respContent= HttpClientUtil.doPost(reqUrl,reqContent);
        logger.info("[支付宝交易]返回内容:{}",respContent);
        //3.处理响应
        ChannelRespParam channelRespParam=convertRespData(respContent,merChannelDto);
        logger.info("[支付宝交易]返回转换后内容:{}",channelRespParam);
        //3.处理响应
        return channelRespParam;
    }

    protected ChannelRespParam convertRespData(String respContent, MerChannelDto merChannelDto) {
        ChannelRespParam channelRespParam=new ChannelRespParam();
        JSONObject respJson= JSONObject.parseObject(respContent);
        String prixStr=getTradeMethod().replace(".","_").toLowerCase();
        String alipayRefundResp=respJson.getString(prixStr+"_response");
        JSONObject alipayTradeRespJson= JSONObject.parseObject(alipayRefundResp);
        String signValue=respJson.getString("sign");
        int firstIndex=respContent.indexOf(":{")+1;
        int endIndex=respContent.indexOf("},")+1;
        String signParam=respContent.substring(firstIndex,endIndex);
        logger.debug("【支付宝交易】待验证签名原字符串:{}",signParam);
        boolean verifyFlag= RSAUtils.verifyWithRsa2(signParam,signValue,merChannelDto.getPubKey());
        if(!verifyFlag){
            logger.info("【支付宝交易】验证签名失败:{}",respJson);
            channelRespParam.setRespCode(ChannelCodeEnum.SIGN_VALID_FAIL.getCode());
            channelRespParam.setRespMsg(ChannelCodeEnum.SIGN_VALID_FAIL.getName());
            return channelRespParam;
        }
        String code=alipayTradeRespJson.getString("code");
        String msg=alipayTradeRespJson.getString("msg");
        if(StringUtils.isNotEmpty(code) && !"10000".equals(code)&&!"40004".equals(code)){
            logger.info("【支付宝交易】接口调用失败:{}",respJson);
            channelRespParam.setRespCode(ChannelCodeEnum.CHANNEL_ERROR.getCode());
            channelRespParam.setRespMsg(msg);
            channelRespParam.setRespContent(respContent);
            return channelRespParam;
        }
        return buildSelfRespData(alipayTradeRespJson,merChannelDto);
    }

    /**
     * 构造自定义请求参数
     * @param merChannelDto
     * @param channelReqParam
     * @return
     */
    public abstract Map buildSelfReqParam(MerChannelDto merChannelDto, ChannelReqParam channelReqParam);

    /**
     * 构造自定义返回参数
     * @param respJson 响应json
     * @param merChannelDto 商户渠道信息
     * @return
     */
    protected abstract ChannelRespParam buildSelfRespData(JSONObject respJson,MerChannelDto merChannelDto);

    private Map buildReqParam(MerChannelDto merChannelDto, ChannelReqParam channelReqParam) {
        Map commonReqParam=new ConcurrentHashMap<>();
        commonReqParam.put("app_id", merChannelDto.getAppId());
        commonReqParam.put("method",getTradeMethod());
        commonReqParam.put("format","json");
        commonReqParam.put("charset","utf-8");
        commonReqParam.put("timestamp", DateUtil.getDateFormat(new Date()));
        commonReqParam.put("version","1.0");
        commonReqParam.put("sign_type", merChannelDto.getSignType());
        //构造自定义参数
        commonReqParam.putAll(buildSelfReqParam(merChannelDto,channelReqParam));
        String content=  PairString.createLinkString(commonReqParam);
        String signValue= RSAUtils.signWithRsa2(content, merChannelDto.getPrivKey());
        commonReqParam.put("sign",signValue);
        return commonReqParam;
    }

}
